import axios from 'axios'
import Vue from 'vue'
import E from 'wangeditor'
import {oss} from '@/utils/alioss.js'
import {cos} from '@/utils/txcos.js'
import {getHeaders, getYMD} from '@/utils/index.js'
import fileDownload from 'js-file-download'

/**
 * 分页请求参数
 * @param param
 */
function getPage (param) {
  let defaultParam = {
    page: 1,
    limit: 10,
    totalCount: 0,
    sidx: '',
    order: ''
  }
  if (typeof param === 'object') {
    return Object.assign({}, defaultParam, param)
  } else {
    return defaultParam
  }
}

/**
 * 获得表格数据
 */
function getTableData (url, param) {
  this.dataLoading = true
  this.$http({
    url: this.$http.adornUrl(url),
    method: 'get',
    params: this.$http.adornParams(param)
  }).then(({data}) => {
    if (data && data.code === 0) {
      this.dataList = data.data.list
      this.q.page = data.data.currPage
      this.q.totalCount = parseInt(data.data.totalCount)
    }
    this.extTableData(data)
    this.dataLoading = false
  })
}

/**
 * 获得表格数据后 额外的逻辑处理 (空方法)
 */
function extTableData (res) {
}

/**
 * 查询
 */
function queryData () {
  this.q.page = 1
  this.getTableData(this.url, this.q)
}

/**
 * 重新加载
 */
function reloadData () {
  this.getTableData(this.url, this.q)
}

/**
 * 分页栏改变每页大小事件
 * @param val
 */
function sizeChange (val) {
  this.q.page = 1
  this.q.limit = val
  this.getTableData(this.url, this.q)
}

/**
 * 分页栏上一页/下一页/指定页数事件
 * @param val
 */
function currentChange (val) {
  this.q.page = val
  this.getTableData(this.url, this.q)
}

/**
 * 复选框 选择/未选择事件
 * @param val
 */
function selectionChange (val) {
  this.dataSelect = val
}

/**
 * 点击table表头排序
 * @param column
 */
function orderSort (column) {
  this.q.page = 1
  this.q.sidx = column.prop
  if (column.order === 'ascending') {
    this.q.order = 'asc'
  } else if (column.order === 'descending') {
    this.q.order = 'desc'
  } else {
    this.q.sidx = 'id'
    this.q.order = 'desc'
  }
  this.getTableData(this.url, this.q)
}

/**
 * 自定义成功提示语
 * @param param
 */
function successTips (param) {
  if (typeof param === 'undefined') {
    param = this.$t('extensionIndexOperatorSuccess')
  }
  if (typeof param === 'string') {
    this.$message({
      message: param,
      type: 'success',
      duration: 1500,
      center: true
    })
  } else if (typeof param === 'object') {
    this.$message(param)
  }
}

/**
 * 自定义错误提示语
 * @param param
 */
function errorTips (param) {
  if (typeof param === 'undefined') {
    param = this.$t('extensionIndexOperatorFail')
  }
  if (typeof param === 'string') {
    this.$message({
      message: param,
      type: 'error',
      center: true
    })
  } else if (typeof param === 'object') {
    this.$message(param)
  }
}

/**
 * 改变状态
 * @param url
 * @param id
 * @param key
 * @param value
 */
function switchValue (url, id, key, value) {
  let param = {id: id}
  if (key) {
    param[key] = value  // 增加当前key value值, 把传递给后台方便后台保存日志
  }
  let adornData = this.$http.adornData(param, false, 'form')
  this.$http({
    url: this.$http.adornUrl(url + '?' + adornData)
  }).then(({data}) => {
    if (data && data.code === 0) {
      this.successTips(this.$t('extensionIndexOperatorSuccess'))
      this.reloadData()
    }
    this.isDisabled = false
  }).catch(error => {
    console.info(error)
    this.errorTips(this.$t('extensionIndexOperatorFail'))
  })
}

/**
 * 确认操作
 * @param url
 * @param id
 * @param tips
 */
function confirmData (url, id, tips) {
  let ids = []
  if (id) {
    ids.push(id)
  } else {
    if (this.dataSelect.length === 0) {
      this.errorTips(this.$t('extensionIndexLeaseOneData'))
      return
    }
    ids = this.dataSelect.map(item => {
      return item.id
    })
  }
  if (tips) {
    tips = `<span style='color: #17B3A3'>${tips}</span>`
  } else {
    tips = this.$t('extensionIndexOperatorData')
  }
  this.$confirm(this.$t('extensionIndexConfirm') + '[' + tips + ']' + this.$t('extensionIndexOperatorDataReally'), this.$t('commonTips'), {
    dangerouslyUseHTMLString: true,
    confirmButtonText: this.$t('commonConfirm'),
    cancelButtonText: this.$t('commonCancel'),
    type: 'warning'
  }).then(({data}) => {
    this.$http({
      url: this.$http.adornUrl(url),
      method: 'post',
      data: this.$http.adornData(ids, false)
    }).then(({data}) => {
      if (data && data.code === 0) {
        this.successTips(this.$t('extensionIndexOperatorSuccess'))
        this.reloadData()
      }
    }).catch(error => {
      console.info(error)
      this.errorTips(this.$t('extensionIndexOperatorFail'))
    })
  })
}

/**
 * 删除
 * @param url 删除请求的url
 * @param id 数据id
 */
function deleteData (url, id) {
  let ids = []
  if (id) {
    ids.push(id)
  } else {
    if (this.dataSelect.length === 0) {
      this.errorTips(this.$t('extensionIndexLeaseOneData'))
      return
    }
    ids = this.dataSelect.map(item => {
      return item.id
    })
  }
  this.$confirm(this.$t('extensionIndexConfirmDeleteData'), this.$t('commonTips'), {
    dangerouslyUseHTMLString: true,
    confirmButtonText: this.$t('commonConfirm'),
    cancelButtonText: this.$t('commonCancel'),
    type: 'warning'
  }).then(() => {
    this.$http({
      url: this.$http.adornUrl(url),
      method: 'post',
      data: this.$http.adornData(ids, false)
    }).then(({data}) => {
      if (data && data.code === 0) {
        this.successTips(this.$t('extensionIndexOperatorSuccess'))
        this.reloadData()
      } else {
        this.errorTips(data.msg)
      }
    })
  }).catch(() => {
  })
}

/**
 * 新增或者更新 初始化
 * @param id
 */
function editHandle (id) {
  this.editHandleExt(id)
  this.editVisible = true
  this.$nextTick(() => {
    this.$refs.edit.init(id)
  })
}

/**
 * 新增或者更新 初始化
 * 额外的逻辑处理 (空方法)
 * @param id
 */
function editHandleExt (id) {
}

/**
 * 查看详情 初始化
 * @param id
 */
function detailHandle (id) {
  this.detailHandleExt(id)
  this.detailVisible = true
  this.$nextTick(() => {
    this.$refs.detail.init(id)
  })
}

/**
 * 查看详情 初始化
 * 额外的逻辑处理 (空方法)
 * @param id
 */
function detailHandleExt (id) {
}

/**
 * 新增或者更新
 * @param param
 * @param saveUrl
 * @param updateUrl
 * @param callback
 */
function saveOrUpdate (param, saveUrl, updateUrl, callback) {
  if (this.isDisabled) {
    this.errorTips(this.$t('extensionIndexDataSubmit'))
    return
  }

  this.$refs.dataForm.validate(valid => {
    if (!valid) {
      return
    }
    this.isDisabled = !this.isDisabled
    let url = param.id ? updateUrl : saveUrl
    this.$http({
      url: this.$http.adornUrl(url),
      method: 'post',
      data: this.$http.adornData(param, false)
    }).then(({data}) => {
      if (data && data.code === 0) {
        if (callback && typeof callback === 'function') {
          callback(data)
        }
        this.successTips(this.$t('extensionIndexOperatorSuccess'))
        this.visible = false
        this.$emit('refreshDataList')
      }
      this.saveOrUpdateExt(data)
      this.isDisabled = false
    })
  })
}

/**
 * 新增或者更新
 * 额外的逻辑处理 (空方法)
 * @param id
 */
function saveOrUpdateExt (data) {
}

/**
 * 编辑数据 初始化省市县下拉框
 */
function initArea (form) {
  if (form.provinceId) {
    this.getRegionInfo(1, 0)
    if (form.cityId) {
      this.getRegionInfo(2, form.provinceId)
      if (form.areaId) {
        this.getRegionInfo(3, form.cityId)
        if (form.streetId) {
          this.getRegionInfo(4, form.areaId)
        }
      }
    }
  }
}

/**
 * 改变省下拉选项
 */
function changeProvince () {
  if (this.form.provinceId) {
    this.$set(this.form, 'cityId', '')
    this.$set(this.form, 'areaId', '')
    this.$set(this.form, 'streetId', '')
    this.getRegionInfo(2, this.form.provinceId)
    this.areaList = []
    this.streetList = []
  }
}

/**
 * 改变市下拉选项
 */
function changeCity () {
  if (this.form.cityId) {
    this.$set(this.form, 'areaId', '')
    this.$set(this.form, 'streetId', '')
    this.getRegionInfo(3, this.form.cityId)
    this.streetList = []
  }
}

/**
 * 改变区域下拉选项
 */
function changeArea () {
  if (this.form.areaId) {
    this.$set(this.form, 'streetId', '')
    this.getRegionInfo(4, this.form.areaId)
  }
}

/**
 * 公用获得省市县联动的方法
 * @param level 等级:1-省份, 2-城市, 3-区域, 4-街道
 * @param parentId
 */
function getRegionInfo (level, parentId) {
  this.$http({
    url: this.$http.adornUrl('/sysRegion/findAll'),
    method: 'post',
    data: this.$http.adornData({level: level, parentId: parentId}, false)
  }).then(({data}) => {
    if (data && data.code === 0) {
      if (level === 1) {
        this.provinceList = data.data
      } else if (level === 2) {
        this.cityList = data.data
      } else if (level === 3) {
        this.areaList = data.data
      } else if (level === 4) {
        this.streetList = data.data
      }
    }
    this.isDisabled = false
  })
}

/**
 * 文件上传成功回调
 */
function fileUploadScs (value, property, fileList) {
  let eleList = this[fileList]
  if (!eleList) {
    this[fileList] = []
  }
  let url = value
  let split = url.split('/')
  eleList.push({
    name: split[split.length - 1],
    url: url
  })
  let result = []
  for (let i = 0; i < eleList.length; i++) {
    result[i] = eleList[i].url
  }
  this.form[property] = result.join()
}

/**
 * 文件移除成功回调
 */
function fileRemove (value, property, fileList) {
  let eleList = this[fileList]
  if (!eleList) {
    return
  }
  let index = -1
  let result = []
  for (let i = 0; i < eleList.length; i++) {
    if (value.url !== eleList[i].url) {
      result.push(eleList[i].url)
    } else {
      index = i
    }
  }
  if (index !== -1) {
    eleList.splice(index, 1)
  }
  this.form[property] = result.join()
}

/**
 * 图片/文件网址处理
 */
function urlListHandle (urls) {
  let urlList = []
  if (urls) {
    let logos = urls.split(',')
    for (let i = 0; i < logos.length; i++) {
      let appU = logos[i].split('/')
      let L = appU[appU.length - 1]
      urlList.push({
        name: L,
        url: logos[i]
      })
    }
  }
  return urlList
}

/**
 * 文件上传存储方式: 1-本地, 2-阿里云, 3-腾讯云
 * @type {number}
 */
window.fileUploadType = 1

/**
 * 上传文件/图片
 * @param params
 * @param property
 * @param fileList
 * @param updatePercent
 * @param callback
 */
function fileUpload (params, property, fileList, updatePercent, callback) {
  if (window.fileUploadType === 1) {
    this.uploadLocalStore(params, property, fileList, callback)
  } else if (window.fileUploadType === 2) {
    this.uploadAliOss(params, property, fileList, updatePercent, callback)
  } else if (window.fileUploadType === 3) {
    this.uploadTxCos(params, property, fileList, updatePercent, callback)
  }
}

/**
 * 上传到本地存储
 * @param params
 * @param property
 * @param fileList
 * @param callback
 */
function uploadLocalStore (params, property, fileList, callback) {
  let uploadData = new FormData()
  uploadData.append('uploadImg', params.file)
  // vue页面使用方法: fileUpload(Object.assign({}, value, {isFile: true, keepName: true}), 'url', 'urlList')
  if (params.isFile) { // 是否为文件类型 而不为图片类型
    uploadData.append('isFile', params.isFile)
  }
  if (params.keepName) { // 保持文件名
    uploadData.append('keepName', params.keepName)
  }
  let config = {
    headers: Object.assign(getHeaders(), {
      'Content-Type': 'multipart/form-data'
    })
  }
  axios.post(this.$http.adornUrl('/fileUpload/save'), uploadData, config)
    .then(res => {
      if (res.data.errno === '0') {
        // params.onSuccess()
        if (property && fileList) {
          this.fileUploadScs(res.data.url, property, fileList)
        }
        if (callback && typeof callback === 'function') {
          callback(res.data.url)
        }
      } else {
        this.errorTips(this.$t('extensionIndexFileUploadFail'))
      }
    }).catch(error => {
      console.info(error)
      this.errorTips(this.$t('extensionIndexFileUploadFail'))
    })
}

/**
 * 上传到阿里云oss
 * @param params
 * @param property
 * @param fileList
 * @param updatePercent 上传回调 更新进度
 * @param callback 上传完成 回调方法
 */
function uploadAliOss (params, property, fileList, updatePercent, callback) {
  let file = params.file
  let fileName = getOssFileName(file)
  let os = oss()
  os.multipartUpload(fileName, file, {
    progress: function (p) {
      if (updatePercent && typeof updatePercent === 'function') {
        updatePercent((p * 100).toFixed(0) + '%')
      }
    }
  }).then(result => {
    let url
    if (result.url) {
      url = result.url
    } else {
      url = os.options.endpoint.protocol + '//' + os.options.bucket + '.' + os.options.endpoint.hostname + '/' + result.name
    }
    if (property && fileList) {
      this.fileUploadScs(url, property, fileList)
    }
    if (callback && typeof callback === 'function') {
      callback(url)
    }
  }).catch(error => {
    console.info(error)
    this.errorTips(this.$t('extensionIndexFileUploadFail'))
  })
}

/**
 * 上传到腾讯COS
 * @param params
 * @param property
 * @param fileList
 * @param updatePercent 上传回调 更新进度
 * @param callback 上传完成 回调方法
 */
function uploadTxCos (params, property, fileList, updatePercent, callback) {
  let file = params.file
  let fileName = getOssFileName(file)
  let cs = cos()
  cs.putObject({
    Bucket: cs.options.Bucket,
    Region: cs.options.Region,
    Key: fileName,
    StorageClass: cs.options.StorageClass,
    Body: file, // 上传文件对象
    onProgress: function (progressData) {
      if (updatePercent && typeof updatePercent === 'function') {
        updatePercent(progressData)
      }
    }
  }).then(data => {
    const location = 'https://' + data.Location
    if (property && fileList) {
      this.fileUploadScs(location, property, fileList)
    }
    if (callback && typeof callback === 'function') {
      callback(location)
    }
  }).catch(err => {
    console.info(err)
    this.errorTips(this.$t('extensionIndexFileUploadFail'))
  })
}

/**
 * 初始化富文本内容
 * @param selector
 * @param editor
 * @param updatePercent
 * @returns {Editor}
 */
function initMultiText (selector, editor, updatePercent) {
  if (editor) {
    editor.destroy()
    editor = null
  }
  editor = new E(selector)
  let _this = this
  let customUpload = (files, insert) => {
    files.forEach(function (file) {
      _this.fileUpload({file: file, isFile: true}, '', '', updatePercent, function (res) {
        insert(res)
      })
    })
  }
  editor.config.customUploadVideo = customUpload
  editor.config.customUploadImg = customUpload
  return editor
}

/**
 * 得到上传阿里云/腾讯云文件名
 * @param file
 * @returns {string}
 */
function getOssFileName (file) {
  if (file && file.name) {
    let number = file.name.lastIndexOf('.') + 1
    let suffix = file.name.substring(number)
    // 生成三位随机数 避免for循环太快导致文件名相同
    let randomNum = Math.floor(Math.random() * (999 - 1 + 1) + 1)
    let dateNow = new Date()
    return getYMD(dateNow) + '/' + dateNow.getTime() + randomNum + '.' + suffix
  }
  return '未找到文件名'
}
/**
 * 下载excel
 * @param url
 * @param params
 * @returns {boolean}
 */
function excelDownload (url, params) {
  let postUrl = this.$http.adornUrl(url)
  let config = {
    headers: getHeaders(),
    responseType: 'blob'
  }
  axios.post(postUrl, params, config).then(response => {
    const contentDisposition = response.headers['content-disposition']
    const regExp = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
    const result = regExp.exec(contentDisposition)
    const filename = decodeURI(result[1])
    fileDownload(response.data, filename)
  })
}

/**
 * get方法请求
 * @param url 请求url
 * @param param 参数
 */
function httpGet (url, param) {
  return new Promise((resolve, reject) => {
    let reqUrl = this.$http.adornUrl(url)
    if (param) {
      let adornData = this.$http.adornData(param, false, 'form')
      // 由于URL带有国际化参数, 所以直接用&拼接即可
      reqUrl += '&' + adornData
    }
    this.$http({
      url: reqUrl
    }).then(({data}) => {
      if (data && data.code === 0) {
        resolve(data)
      }
    }).catch(error => {
      console.info(error)
      this.errorTips('Get Request Failed')
      reject(error)
    })
  })
}

/**
 * 通过menuId 找到对应的路由信息
 * @param menuId
 * @returns {string|*}
 */
function getRouteByMenuId (menuId) {
  let dynamicMenuRoutes = JSON.parse(sessionStorage.getItem('dynamicMenuRoutes') || '[]')
  let route = dynamicMenuRoutes.filter(item => item.meta.menuId === menuId)
  if (route.length >= 1) {
    return route[0]
  } else {
    return null
  }
}

/**
 * 初始化列表全部列
 */
function getColData () {
  let result = []
  for (let i = 0; i < arguments.length; i++) {
    result.push({title: arguments[i], isTrue: true})
  }
  return result
}

/**
 * 初始化列表需要显示的列
 */
function initDynamicColumn () {
  // 列筛选
  this.colData.forEach((item, index) => {
    this.checkBoxGroup.push(item.title)
    this.checkedColumns.push(item.title)
  })
  // 从浏览器缓存 获取要显示的列
  let showColumn = window.localStorage.getItem(window.SITE_CONFIG['dynamicColumnKey'] + this.url)
  if (showColumn && showColumn !== 'undefined') {
    showColumn = JSON.parse(showColumn)
    this.checkedColumns = showColumn
    this.colData.filter(i => {
      i.isTrue = showColumn.indexOf(i.title) !== -1
    })
  }
}

/**
 * 切换列表的列动态显示/隐藏
 * @param showColumn 需要显示列
 */
function dynamicColumn (showColumn) {
  // 浏览器缓存要显示的列, 使用url作为key
  window.localStorage.setItem(window.SITE_CONFIG['dynamicColumnKey'] + this.url, JSON.stringify(showColumn))
  this.colData.filter(i => {
    i.isTrue = showColumn.indexOf(i.title) !== -1
  })
  this.reload = Math.random()
}

/**
 * 清空缓存的动态列信息
 * @param specialKey 指定需要清空的key, 不指定则清空所有
 */
function clearDynamicColumn (specialKey) {
  if (specialKey != null) {
    window.localStorage.removeItem(window.SITE_CONFIG['dynamicColumnKey'] + specialKey)
  } else {
    let keys = Object.keys(window.localStorage) // 得到所有缓存的动态列
    for (let key of keys) {
      if (key.indexOf(window.SITE_CONFIG['dynamicColumnKey']) !== -1) {
        window.localStorage.removeItem(key)
      }
    }
  }
}

/**
 * 获得年月日
 * @param date 时间字符串 或者时间对象
 * @returns {*}
 */
function getDateYMD (date) {
  return getYMD(date)
}

// 手机号验证
let validatePhone = (rule, value, callback) => {
  if (value == null || value === '' || typeof value === 'undefined') {
    return callback(new Error(rule.notNullTips))
  }
  let regFormat = /^[1][3456789][0-9]{9}$/
  if (!(regFormat.test(value))) {
    callback(new Error(rule.phone))
  } else {
    callback()
  }
}

// 身份证验证
let validateIdCard = (rule, value, callback) => {
  const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
  if (value == null || value === '' || typeof value === 'undefined') {
    return callback(new Error(rule.notNullTips))
  } else if (!reg.test(value)) {
    return callback(new Error(rule.idCard))
  } else {
    callback()
  }
}

// 邮箱验证
let validateEmail = (rule, value, callback) => {
  // eslint-disable-next-line no-useless-escape
  let mal = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
  if (value == null || value === '' || typeof value === 'undefined') {
    return callback(new Error(rule.notNullTips))
  }
  if (!(mal.test(value))) {
    callback(new Error(rule.email))
  } else {
    callback()
  }
}

// 整数验证
let validateInteger = (rule, value, callback) => {
  if (value == null || value === '' || typeof value === 'undefined') {
    return callback(new Error(rule.notNullTips))
  }
  if (!/^[0-9]*$/.test(value)) {
    callback(new Error(rule.intNumber))
  } else {
    callback()
  }
}

// 数字包含小数验证
let validateNumber = (rule, value, callback) => {
  if (value == null || value === '' || typeof value === 'undefined') {
    return callback(new Error(rule.notNullTips))
  }
  if (!/^[0-9]+([.][0-9]+)?$/.test(value)) {
    callback(new Error(rule.digitNumber))
  } else {
    let precision = rule.precision // 规定小数位长度
    if (precision) {
      let tv = value + ''
      if (tv.indexOf('.') > 0) { // 输入值带有小数
        let valSplit = tv.split('.')
        let valPre = valSplit[1].length // 输入值小数位长度
        if (valPre > parseInt(precision)) {
          let digitNumberErr = rule.digitNumberErr
          callback(new Error(digitNumberErr + parseInt(precision)))
        } else {
          callback()
        }
      } else {
        callback()
      }
    } else {
      callback()
    }
  }
}

// 英文验证
let validateEnglish = (rule, value, callback) => {
  if (value == null || value === '' || typeof value === 'undefined') {
    return callback(new Error(rule.notNullTips))
  }
  if (!/^[A-Za-z]+$/.test(value)) {
    callback(new Error(rule.eng))
  } else {
    callback()
  }
}

// 字符串不能为空验证
let validateNotNull = (rule, value, callback) => {
  if (value == null || value === '' || typeof value === 'undefined') {
    return callback(new Error(rule.notNullTips))
  } else {
    let range = rule.range
    if (range) {
      let split = range.split('-')
      if (split.length === 1) {
        let max = parseInt(split[0])
        if (value.length > max) {
          let rangeErr = rule.rangeErr
          return callback(new Error(rangeErr + range))
        } else {
          callback()
        }
      } else {
        let min = parseInt(split[0])
        let max = parseInt(split[1])
        if (value.length < min || value.length > max) {
          let rangeErr = rule.rangeErr
          return callback(new Error(rangeErr + range))
        } else {
          callback()
        }
      }
    } else {
      callback()
    }
  }
}

// 校验对象
function getRules () {
  let notNull = this.$t('extensionIndexValueNotNull')
  let phone = this.$t('extensionIndexValidPhone')
  let idCard = this.$t('extensionIndexValidIdCard')
  let email = this.$t('extensionIndexValidEmail')
  let intNumber = this.$t('extensionIndexValidIntNumber')
  let digitNumber = this.$t('extensionIndexValidDigitNumber')
  let digitNumberErr = this.$t('extensionIndexValidPrecision')
  let rangeErr = this.$t('extensionIndexValidRange')
  let eng = this.$t('extensionIndexValidEng')
  return {
    isPhone: [{required: true, validator: validatePhone, trigger: 'blur', notNullTips: notNull, phone: phone}],
    isIdCard: [{required: true, validator: validateIdCard, trigger: 'blur', notNullTips: notNull, idCard: idCard}],
    isInteger: [{required: true, validator: validateInteger, trigger: 'blur', notNullTips: notNull, intNumber: intNumber}],
    isNumber: (precision) => {
      return [{required: true, validator: validateNumber, trigger: 'blur', precision: precision, notNullTips: notNull, digitNumber: digitNumber, digitNumberErr: digitNumberErr}]
    },
    isEnglish: [{required: true, validator: validateEnglish, trigger: 'blur', notNullTips: notNull, eng: eng}],
    isEmail: [{required: true, validator: validateEmail, trigger: 'blur', notNullTips: notNull, email: email}],
    isNotNull: [{required: true, validator: validateNotNull, trigger: 'blur', notNullTips: notNull}],
    isRange: (range) => {
      return [{required: true, validator: validateNotNull, trigger: 'blur', range: range, notNullTips: notNull, rangeErr: rangeErr}]
    }
  }
}

Vue.prototype.getPage = getPage
Vue.prototype.getTableData = getTableData
Vue.prototype.extTableData = extTableData
Vue.prototype.queryData = queryData
Vue.prototype.reloadData = reloadData
Vue.prototype.sizeChange = sizeChange
Vue.prototype.currentChange = currentChange
Vue.prototype.selectionChange = selectionChange
Vue.prototype.orderSort = orderSort
Vue.prototype.successTips = successTips
Vue.prototype.errorTips = errorTips
Vue.prototype.deleteData = deleteData
Vue.prototype.editHandle = editHandle
Vue.prototype.editHandleExt = editHandleExt
Vue.prototype.detailHandle = detailHandle
Vue.prototype.detailHandleExt = detailHandleExt
Vue.prototype.saveOrUpdate = saveOrUpdate
Vue.prototype.saveOrUpdateExt = saveOrUpdateExt
Vue.prototype.initArea = initArea
Vue.prototype.changeProvince = changeProvince
Vue.prototype.changeCity = changeCity
Vue.prototype.changeArea = changeArea
Vue.prototype.getRegionInfo = getRegionInfo
Vue.prototype.fileUploadScs = fileUploadScs
Vue.prototype.fileRemove = fileRemove
Vue.prototype.urlListHandle = urlListHandle
Vue.prototype.fileUpload = fileUpload
Vue.prototype.uploadAliOss = uploadAliOss
Vue.prototype.uploadTxCos = uploadTxCos
Vue.prototype.uploadLocalStore = uploadLocalStore
Vue.prototype.initMultiText = initMultiText
Vue.prototype.getRules = getRules
Vue.prototype.switchValue = switchValue
Vue.prototype.confirmData = confirmData
Vue.prototype.excelDownload = excelDownload
Vue.prototype.httpGet = httpGet
Vue.prototype.getRouteByMenuId = getRouteByMenuId
Vue.prototype.initDynamicColumn = initDynamicColumn
Vue.prototype.dynamicColumn = dynamicColumn
Vue.prototype.clearDynamicColumn = clearDynamicColumn
Vue.prototype.getColData = getColData
Vue.prototype.getDateYMD = getDateYMD
